package jp.sourceforge.akjrcp.text_douga.views.syncsubimages;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import com.akjava.lib.commons.time.TimeUtils;

import jp.sourceforge.akjrcp.ffmpeg.FFMpegFLVParser;
import jp.sourceforge.akjrcp.ffmpeg.FLVInfomation;
import jp.sourceforge.akjrcp.subtitle.StandardSubObject;



public class SyncSubBuilder {
	private List<SyncImageData> syncImageDataList=new ArrayList<SyncImageData>();
	private File[] beforeFiles;
	String audioPath;
	String ffmpegPath;
	private int expandTime=4;
   private long audioOffset;
	public List<ResultData> buildText(){
		List<ResultData> results=new ArrayList<ResultData>();
		double audioTime=(double)getAudioDuration()/1000.0;
		SyncSubImageView.log.info("audioTime:"+audioTime);
		SyncImageData[] syncDatas=syncImageDataList.toArray(new SyncImageData[syncImageDataList.size()]);
		
		//before text.
		
		int index=0;
		if(beforeFiles!=null){
			double startTime=0;
			double endTime=expandTime;//default for rate case
			boolean finded=false;
			for(int i=index;i<syncDatas.length;i++){
				SyncImageData sdata=syncDatas[i];
				if(sdata.haveInsideFiles()){
					endTime=sdata.getSubtitle().getStartTimeAsDouble();
					finded=true;
					break;
				}else if(sdata.haveAfterFiles()){
					endTime=sdata.getSubtitle().getEndTimeAsDouble();
					finded=true;
					break;
				}
				if(!finded){
					index++;//skip
				}
			}
			
			if(!finded && audioTime!=0){
				endTime=audioTime;
			}
			toTexts(results,beforeFiles,startTime,endTime);
		}
		
		for (int j = index; j < syncDatas.length;j++) {
			SyncImageData sdata=syncDatas[j];
			File[] insides=sdata.getInsideFiles();
			File[] afters=sdata.getAfterFiles();
			
			if(sdata.haveInsideFiles()){
				if(sdata.haveAfterFiles()){//between in subtitle
					toTexts(results,insides,sdata.getSubtitle().getStartTimeAsDouble(),sdata.getSubtitle().getEndTimeAsDouble());
				
					double startTime=sdata.getSubtitle().getEndTimeAsDouble();
					double endTime=sdata.getSubtitle().getEndTimeAsDouble()+expandTime;
					boolean finded=false;
					for(int i=j+1;i<syncDatas.length;i++){
						SyncImageData sdata2= syncDatas[i];
						if(sdata2.haveInsideFiles()){
							endTime=sdata2.getSubtitle().getStartTimeAsDouble();
							finded=true;
							break;
						}else if(sdata2.haveAfterFiles()){
							endTime=sdata2.getSubtitle().getEndTimeAsDouble();
							finded=true;
							break;
						}
						
					}
					if(!finded && audioTime>0 && audioTime>sdata.getSubtitle().getEndTimeAsDouble()){
						endTime=audioTime;
					}
					toTexts(results,afters,startTime,endTime);
				}else{
				double startTime=sdata.getSubtitle().getStartTimeAsDouble();
				double endTime=sdata.getSubtitle().getEndTimeAsDouble();
				boolean finded=false;
				//find end
				for(int i=j+1;i<syncDatas.length;i++){
					SyncImageData sdata2= syncDatas[i];
					if(sdata2.haveInsideFiles()){
						endTime=sdata2.getSubtitle().getStartTimeAsDouble();
						finded=true;
						break;
					}else if(sdata2.haveAfterFiles()){
						endTime=sdata2.getSubtitle().getEndTimeAsDouble();
						finded=true;
						break;
					}
				}
				if(!finded){
					if(audioTime>endTime){
						endTime=audioTime;
					}
				}
				SyncSubImageView.log.trace("endtime:"+endTime);
				toTexts(results,insides,startTime,endTime);
				}
			}else{//before is null
				if(sdata.haveAfterFiles()){
					double startTime=sdata.getSubtitle().getEndTimeAsDouble();
					double endTime=sdata.getSubtitle().getEndTimeAsDouble()+expandTime;
					boolean finded=false;
					for(int i=j+1;i<syncDatas.length;i++){
						SyncImageData sdata2= syncDatas[i];
						if(sdata2.haveInsideFiles()){
							endTime=sdata2.getSubtitle().getStartTimeAsDouble();
							finded=true;
							break;
						}else if(sdata2.haveAfterFiles()){
							endTime=sdata2.getSubtitle().getEndTimeAsDouble();
							finded=true;
							break;
						}
						
					}
					if(!finded && audioTime>0 && audioTime>sdata.getSubtitle().getEndTimeAsDouble()){
						endTime=audioTime;
					}
					toTexts(results,afters,startTime,endTime);
				}
			}
			
		}
		
		
return results;
	}
	
	public static class SyncImageData{
		private StandardSubObject subtitle;
		private File[] insideFiles;
		private File[] afterFiles;
		public SyncImageData(StandardSubObject subtitle,File[] insideFiles,File[] afterFiles){
			this.subtitle=subtitle;
			this.insideFiles=insideFiles;
			this.afterFiles=afterFiles;
		}
		public StandardSubObject getSubtitle() {
			return subtitle;
		}
		public File[] getInsideFiles() {
			return insideFiles;
		}
		public boolean haveInsideFiles(){
			return insideFiles!=null && insideFiles.length>0;
		}
		public File[] getAfterFiles() {
			return afterFiles;
		}
		public boolean haveAfterFiles(){
			return afterFiles!=null && afterFiles.length>0;
		}
	}

	public File[] getBeforeFiles() {
		return beforeFiles;
	}

	public String getAudioPath() {
		return audioPath;
	}
	public long getAudioDuration(){
		long ret=0;
		if(audioPath!=null){
			FFMpegFLVParser parser=new FFMpegFLVParser(ffmpegPath);
			
			FLVInfomation info=parser.parseFile(new File(audioPath));
			//System.out.println(parser.getLogText());
			if(info.getDuration()!=null){
				int vs[]=TimeUtils.toHourMinSecMilliSecond(info.getDuration());
				if(vs[3]<100){
				vs[3]*=10;//ffmpeg ms is 1000/10
				}
				ret=TimeUtils.toMillisecond(vs[0], vs[1], vs[2], vs[3]);
				ret-=audioOffset;
			}
		}
		return ret;
	}
	public static class ResultData{
		private double start;
		private double duration;
		private String path;
		public ResultData(String path,double start,double duration){
			this.start=start;
			this.duration=duration;
			this.path=path;
		}
		public String toString(){
			String header="#start="+TimeUtils.toBigDecimalTime(start)+",duration="+TimeUtils.toBigDecimalTime(duration)+"\n";
			header+=path+"\n";
			return header;
		}
		public boolean equals(Object data){
			if(data instanceof ResultData){
				ResultData rd=(ResultData)data;
				String rdT=""+rd.path;
				return rd.start==this.start && rd.duration ==this.duration && rdT.equals(""+path);
			}
			return false;
		}
	}
	public void toTexts(List<ResultData> results,File[] files,double start,double end){
		if(files!=null && files.length>0){
			double d=(end-start)/files.length;
			
			double duration=TimeUtils.toBigDecimalTime(d);
			double current=0;
			
			for(int i=0;i<files.length;i++){
				double startValue=start+current;
				double durationValue;
				if(i==files.length-1){//last
					durationValue=end-(current+start);//diff last
				}else{
					durationValue=duration;
				}
				current+=duration;
				results.add(new ResultData(files[i].getAbsolutePath(),startValue,durationValue));
			}
		}
	}

	public List<SyncImageData> getSyncImageDatas() {
		return syncImageDataList;
	}

	public void setSyncImageDatas(List<SyncImageData> syncImageDatas) {
		this.syncImageDataList = syncImageDatas;
	}

	public void setBeforeFiles(File[] beforeFiles) {
		this.beforeFiles = beforeFiles;
	}

	public void setAudioPath(String audioPath) {
		this.audioPath = audioPath;
	}

	public String getFfmpegPath() {
		return ffmpegPath;
	}

	public void setFfmpegPath(String ffmpegPath) {
		this.ffmpegPath = ffmpegPath;
	}

	public long getAudioOffset() {
		return audioOffset;
	}

	public void setAudioOffset(long audioOffset) {
		this.audioOffset = audioOffset;
	}
}
